/*
 *      A Stock Market Simulator Skeleton
 *      by Nikos Pitsianis - Implementation by Elias Kyrlies-Chrysoulidis
 *
 *	Based upon the pc.c producer-consumer demo by Andrae Muys
 */

#include <stdio.h>
#include <math.h>
#include <stdlib.h>	
#include <time.h>	
#include <sys/time.h>
#include <string.h>
#include <unistd.h>		
#include <pthread.h>
#include "stock_lib.h"
#include "stock_lib.c"

// ****************************************************************
int main() {

	// reset number generator seed
	// srand(time(NULL) + getpid());
	srand(0); // to get the same sequence

	// start the time for timestamps
	gettimeofday (&startwtime, NULL);
  

	pthread_t prod, cons, trans, bmsl, bmsm, blsl,blsm, sstop, bstop, cancel,force ,blstop,slstop ;
	queue *q = queueInit();
	arguments args;
  
	// Initialize all queues 
	args.b = queueInit();
	args.s = queueInit();
	args.bl = queueInit();
	args.sl = queueInit();
	args.sstop = queueInit();
	args.bstop = queueInit();
	args.cancel= queueInit();
	args.slstop = queueInit();
	args.blstop = queueInit();
	args.q = q;

	// open log file
	f = fopen("trace.txt","wt");

	// Initialize mutexes
	pthread_mutex_init(&mut, NULL);        // General mutex
	pthread_mutex_init(&price, NULL);      // Mutex locks transactions
	pthread_mutex_init(&file, NULL);       // Mutex locks log file 


	//=============================
	//-----Create threads---------
	//=============================

	pthread_create(&prod, NULL, Prod, q);         
  
	pthread_create(&cons, NULL, Cons, &args);     


	// Main transaction threads
	pthread_create(&bmsm, NULL, BuyMarketSellMarket, &args); 
	pthread_create(&bmsl, NULL, BuyMarketSellLimit, &args);  
	pthread_create(&blsm, NULL, BuyLimitSellMarket, &args);
	pthread_create(&blsl, NULL, BuyLimitSellLimit, &args);
  
	// Stop and Cacnel Queue threads
	pthread_create(&bstop, NULL, BStop, &args);
	pthread_create(&sstop, NULL, SStop, &args);
	pthread_create(&blstop,NULL,BStopLimit, &args);
	pthread_create(&slstop,NULL,SStopLimit,&args);
	pthread_create(&cancel, NULL, Cancel, &args );

	// Janitor thread
	pthread_create(&force, NULL, forceTrans, &args);


	// I actually do not expect them to ever terminate
	pthread_join(prod, NULL);
	pthread_join(cons, NULL);
	pthread_join(bmsm, NULL);
	pthread_join(bmsl, NULL);
	pthread_join(blsm, NULL);
	pthread_join(blsl, NULL);
	pthread_join(sstop,NULL);
	pthread_join(bstop,NULL);
	pthread_join(cancel,NULL);
	pthread_join(blstop,NULL);
	pthread_join(slstop,NULL);
	pthread_join(force,NULL);


	pthread_exit(NULL);
}


